#include "FunctionFactory.hpp"
#include "FunctionFactoryDetails.hpp"
#include "FunctionFactoryCollection.hpp"

void FunctionFactory::loadBuiltIns()
{
	insertFunction("operator+", &operatorAdd);
	insertFunction("operator-", &operatorSub);
	insertFunction("operator*", &operatorMul);
	insertFunction("operator/", &operatorDiv);
	insertFunction("operator%", &operatorMod);
	insertFunction("operator|", &operatorOr);
	insertFunction("operator&", &operatorAnd);
	insertFunction("operator^", &operatorXor);
	insertFunction("operator<<", &operatorShL);
	insertFunction("operator>>", &operatorShR);
	insertFunction("operator~", &operatorInv);
	insertFunction("operator-", &operatorNeg);
	insertFunction("operator+", &operatorPos);
	insertFunction("operator!", &operatorBoolNot);
	insertFunction("operator&", &operatorBoolAnd);
	insertFunction("operator|", &operatorBoolOr);
	insertFunction("operator^", &operatorBoolXor);
	insertFunction("operator<", &operatorCmpLNGE<int>);
	insertFunction("operator>", &operatorCmpGNLE<int>);
	insertFunction("operator==", &operatorCmpENLG<int>);
	insertFunction("operator>=", &operatorCmpGENL<int>);
	insertFunction("operator<=", &operatorCmpLENG<int>);
	insertFunction("operator!=", &operatorCmpLGNE<int>);
	insertFunction("operator$", &operatorConcat);
	insertFunction("operator<", &operatorCmpLNGE<String const &>);
	insertFunction("operator>", &operatorCmpGNLE<String const &>);
	insertFunction("operator==", &operatorCmpENLG<String const &>);
	insertFunction("operator>=", &operatorCmpGENL<String const &>);
	insertFunction("operator<=", &operatorCmpLENG<String const &>);
	insertFunction("operator!=", &operatorCmpLGNE<String const &>);
	insertFunction("operator:=", &operatorAssign<bool>);
	insertFunction("operator:=", &operatorAssign<int>);
	insertFunction("operator:=", &operatorAssign<String const &>);
	insertFunction("operator+=", &operatorAdd);
	insertFunction("operator-=", &operatorSub);
	insertFunction("operator*=", &operatorMul);
	insertFunction("operator/=", &operatorDiv);
	insertFunction("operator%=", &operatorMod);
	insertFunction("operator|=", &operatorOr);
	insertFunction("operator&=", &operatorAnd);
	insertFunction("operator^=", &operatorXor);
	insertFunction("operator<<=", &operatorShL);
	insertFunction("operator>>=", &operatorShR);
	insertFunction("operator&=", &operatorBoolAnd);
	insertFunction("operator|=", &operatorBoolOr);
	insertFunction("operator^=", &operatorBoolXor);
	insertFunction("operator$=", &operatorConcat);
	insertFunction("iif", &functionIif<bool>);
	insertFunction("iif", &functionIif<int>);
	insertFunction("iif", &functionIif<String const &>);
	insertFunction("abs", &functionAbs<int>);
	insertFunction("min", &functionMin<int>);
	insertFunction("max", &functionMax<int>);
	insertFunction("left", &functionLeft);
	insertFunction("right", &functionRight);
	insertFunction("mid", &functionMid1);
	insertFunction("mid", &functionMid2);
	insertFunction("subst", &functionSubst<bool>);
	insertFunction("subst", &functionSubst<int>);
	insertFunction("subst", &functionSubst<String const &>);
	insertFunction("iter", &functionIterate0);
	insertFunction("iter", &functionIterate1);
	insertFunction("list", &functionList0);
	insertFunction("list", &functionList1);
	insertFunction("list", &functionList2);
	insertFunction("list", &functionList3);
	insertFunction("listx", &functionListX0);
	insertFunction("listx", &functionListX1);
	insertFunction("listx", &functionListX2);
	insertFunction("listx", &functionListX3);
	insertFunction("classArgs", &functionClassArgs0);
	insertFunction("classArgs", &functionClassArgs1);
	insertFunction("classArgs", &functionClassArgs2);
	insertFunction("classArgs", &functionClassArgs3);
	insertFunction("selArgs", &functionSelArgs0);
	insertFunction("selArgs", &functionSelArgs1);
	insertFunction("selArgs", &functionSelArgs2);
	insertFunction("selArgs", &functionSelArgs3);
	insertFunction("funcArgs", &functionFuncArgs0);
	insertFunction("funcArgs", &functionFuncArgs1);
	insertFunction("funcArgs", &functionFuncArgs2);
	insertFunction("funcArgs", &functionFuncArgs3);
	insertFunction("callArgs", &functionCallArgs0);
	insertFunction("callArgs", &functionCallArgs1);
	insertFunction("callArgs", &functionCallArgs2);
	insertFunction("callArgs", &functionCallArgs3);
}

ptr<Function> FunctionFactory::getFunction(FunctionSignature const & signature) const
{
	FunctionsDatabase::const_iterator it = database_.find(signature);
	if(it == database_.end()) return ptr<Function>();
	return it->second;
}

void FunctionFactory::insertFunction(ptr<Function> const & func)
{
	assert(database_.count(func->signature()) == 0);
	database_.insert(std::make_pair(func->signature(), func));
}

template<class T> void FunctionFactory::insertFunction(String const & name, T pFunc)
{
	ptr<Function> func(new FunctionT<T>(name, pFunc));
	insertFunction(func);
}